home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / Tool Chest / Games / Game Sample Code / SpriteWorld 1.0b3 / Sources / Sprite.c < prev    next >
Encoding:
Text File  |  1993-06-07  |  24.5 KB  |  934 lines  |  [TEXT/KAHL]

  1. ///--------------------------------------------------------------------------------------
  2. //    Sprite.c
  3. //
  4. //    Created:    Tuesday, October, 1992 at 10:10:06 PM
  5. //    By:        Tony Myles
  6. //
  7. //    Copyright: © 1991-93 Tony Myles, All rights reserved worldwide
  8. //
  9. //    Description:    implementation of the sprites
  10. ///--------------------------------------------------------------------------------------
  11.  
  12.  
  13. #ifndef __MEMORY__
  14. #include <Memory.h>
  15. #endif
  16.  
  17. #ifndef __SPRITEWORLDUTILS__
  18. #include <SpriteWorldUtils.h>
  19. #endif
  20.  
  21. #ifndef __SPRITEWORLD__
  22. #include <SpriteWorld.h>
  23. #endif
  24.  
  25. #ifndef __SPRITE__
  26. #include <Sprite.h>
  27. #endif
  28.  
  29. #ifndef __FRAME__
  30. #include <Frame.h>
  31. #endif
  32.  
  33.  
  34. ///--------------------------------------------------------------------------------------
  35. //    SWCreateSprite
  36. ///--------------------------------------------------------------------------------------
  37.  
  38. SW_PASCAL OSErr SWCreateSprite(
  39.     SpritePtr* newSpriteP,
  40.     void* spriteStorageP,
  41.     short maxFrames)
  42. {
  43.     OSErr err = noErr;
  44.     SpritePtr tempSpriteP;
  45.     Size frameArraySize;
  46.  
  47.     *newSpriteP = NULL;
  48.  
  49.         // use NewPtrClear so we don’t have to initialize everything to zero
  50.     tempSpriteP = (SpritePtr) (spriteStorageP == NULL) ? NewPtr(sizeof(SpriteRec)) : spriteStorageP;
  51.  
  52.     if (tempSpriteP != NULL)
  53.     {
  54.         frameArraySize = (Size)(maxFrames * sizeof(FramePtr));
  55.  
  56.         tempSpriteP->frameArray = (FramePtr *)NewPtrClear(frameArraySize);
  57.  
  58.         if (tempSpriteP->frameArray != NULL)
  59.         {
  60.             tempSpriteP->nextSpriteP = NULL;
  61.             tempSpriteP->prevSpriteP = NULL;
  62.  
  63.                 // initialize drawing fields
  64.             tempSpriteP->isVisible = true;
  65.             tempSpriteP->needsToBeDrawn = true;
  66.             tempSpriteP->needsToBeErased = false;
  67.             tempSpriteP->destFrameRect.left = 0;
  68.             tempSpriteP->destFrameRect.top = 0;
  69.             tempSpriteP->destFrameRect.right = 0;
  70.             tempSpriteP->destFrameRect.bottom = 0;
  71.             tempSpriteP->oldFrameRect.left = 0;
  72.             tempSpriteP->oldFrameRect.top = 0;
  73.             tempSpriteP->oldFrameRect.right = 0;
  74.             tempSpriteP->oldFrameRect.bottom = 0;
  75.             tempSpriteP->deltaFrameRect.left = 0;
  76.             tempSpriteP->deltaFrameRect.top = 0;
  77.             tempSpriteP->deltaFrameRect.right = 0;
  78.             tempSpriteP->deltaFrameRect.bottom = 0;
  79.             tempSpriteP->screenMaskRgn = NULL;
  80.             tempSpriteP->frameDrawProc = SWStdDrawProc;
  81.  
  82.                 // initialize frame fields
  83.             tempSpriteP->frameTimeTask.timeTask.tmAddr = SWTimeTask;
  84.             tempSpriteP->frameTimeTask.timeTask.qLink = NULL;
  85.             tempSpriteP->frameTimeTask.timeTask.qType = 0;
  86.             tempSpriteP->frameTimeTask.timeTask.tmCount = 0;
  87.             tempSpriteP->frameTimeTask.timeTask.tmWakeUp = 0;
  88.             tempSpriteP->frameTimeTask.timeTask.tmReserved = 0;
  89.             tempSpriteP->frameTimeTask.hasTaskFired = false;
  90.             tempSpriteP->curFrameP = NULL;
  91.             tempSpriteP->numFrames = 0;
  92.             tempSpriteP->maxFrames = maxFrames;
  93.             tempSpriteP->frameTimeInterval = -1;
  94.             tempSpriteP->frameAdvance = 1;
  95.             tempSpriteP->curFrameIndex = 0;
  96.             tempSpriteP->firstFrameIndex = 0;
  97.             tempSpriteP->lastFrameIndex = 0;
  98.             tempSpriteP->frameChangeProc = NULL;
  99.  
  100.                 // initialize movement fields
  101.             tempSpriteP->moveTimeTask.timeTask.tmAddr = SWTimeTask;
  102.             tempSpriteP->moveTimeTask.timeTask.qLink = NULL;
  103.             tempSpriteP->moveTimeTask.timeTask.qType = 0;
  104.             tempSpriteP->moveTimeTask.timeTask.tmCount = 0;
  105.             tempSpriteP->moveTimeTask.timeTask.tmWakeUp = 0;
  106.             tempSpriteP->moveTimeTask.timeTask.tmReserved = 0;
  107.             tempSpriteP->moveTimeTask.hasTaskFired = true;
  108.             tempSpriteP->moveTimeInterval = 0;
  109.             tempSpriteP->horizMoveDelta = 0;
  110.             tempSpriteP->vertMoveDelta = 0;
  111.             tempSpriteP->moveBoundsRect.left = 0;
  112.             tempSpriteP->moveBoundsRect.top = 0;
  113.             tempSpriteP->moveBoundsRect.right = 0;
  114.             tempSpriteP->moveBoundsRect.bottom = 0;
  115.             tempSpriteP->spriteMoveProc = NULL;
  116.  
  117.                 // collision detection fields
  118.             tempSpriteP->collideRect.left = 0;
  119.             tempSpriteP->collideRect.top = 0;
  120.             tempSpriteP->collideRect.right = 0;
  121.             tempSpriteP->collideRect.bottom = 0;
  122.             tempSpriteP->spriteCollideProc = NULL;
  123.  
  124.             tempSpriteP->userData = 0;
  125.  
  126.                 // insert the sprite time tasks into the time manager queue
  127.             InsTime((QElemPtr)&tempSpriteP->moveTimeTask);
  128.             InsTime((QElemPtr)&tempSpriteP->frameTimeTask);
  129.  
  130.                 // the sprite has been successfully created
  131.             *newSpriteP = tempSpriteP;
  132.         }
  133.         else
  134.         {
  135.             err = MemError();
  136.  
  137.             DisposePtr((Ptr)tempSpriteP);
  138.         }
  139.     }
  140.     else
  141.     {
  142.         err = MemError();
  143.     }
  144.  
  145.     return err;
  146. }
  147.  
  148.  
  149. ///--------------------------------------------------------------------------------------
  150. //    SWCreateSpriteFromCIconResource
  151. ///--------------------------------------------------------------------------------------
  152.  
  153. SW_PASCAL OSErr SWCreateSpriteFromCIconResource(
  154.     SpritePtr* newSpriteP,
  155.     void* spriteStorageP,
  156.     short cIconID,
  157.     short maxFrames,
  158.     MaskType maskType)
  159. {
  160.     OSErr err;
  161.     SpritePtr tempSpriteP;
  162.     FramePtr newFrameP;
  163.     short frame;
  164.  
  165.     *newSpriteP = NULL;
  166.  
  167.     err = SWCreateSprite(&tempSpriteP, spriteStorageP, maxFrames);
  168.  
  169.     if (err == noErr)
  170.     {
  171.         for (frame = 0; frame < maxFrames; frame++)
  172.         {
  173.             err = SWCreateFrameFromCIconResource(&newFrameP, cIconID + frame, maskType);
  174.  
  175.             if (err == noErr)
  176.             {
  177.                 err = SWAddFrame(tempSpriteP, newFrameP);
  178.             }
  179.  
  180.             if (err != noErr)
  181.             {
  182.                 SWDisposeFrame(newFrameP);
  183.                 SWDisposeSprite(tempSpriteP, true);
  184.                 break;
  185.             }
  186.         }
  187.  
  188.         if (err == noErr)
  189.         {
  190.             *newSpriteP = tempSpriteP;
  191.         }
  192.     }
  193.  
  194.     return err;
  195. }
  196.  
  197.  
  198. ///--------------------------------------------------------------------------------------
  199. //    SWCreateSpriteFromPictResource
  200. ///--------------------------------------------------------------------------------------
  201.  
  202. SW_PASCAL OSErr SWCreateSpriteFromPictResource(
  203.     SpritePtr* newSpriteP,
  204.     void* spriteStorageP,
  205.     short pictResID,
  206.     short maskResID,
  207.     short maxFrames,
  208.     MaskType maskType)
  209. {
  210.     OSErr err;
  211.     SpritePtr tempSpriteP;
  212.     FramePtr newFrameP;
  213.     short frame;
  214.  
  215.     *newSpriteP = NULL;
  216.  
  217.     err = SWCreateSprite(&tempSpriteP, spriteStorageP, maxFrames);
  218.  
  219.     if (err == noErr)
  220.     {
  221.         for (frame = 0; frame < maxFrames; frame++)
  222.         {
  223.             err = SWCreateFrameFromPictResource(&newFrameP, pictResID + frame, maskResID + frame, maskType);
  224.  
  225.             if (err == noErr)
  226.             {
  227.                 err = SWAddFrame(tempSpriteP, newFrameP);
  228.             }
  229.  
  230.             if (err != noErr)
  231.             {
  232.                 SWDisposeFrame(newFrameP);
  233.                 SWDisposeSprite(tempSpriteP, true);
  234.                 break;
  235.             }
  236.         }
  237.  
  238.         if (err == noErr)
  239.         {
  240.             *newSpriteP = tempSpriteP;
  241.         }
  242.     }
  243.     
  244.     return err;
  245. }
  246.  
  247.  
  248. ///--------------------------------------------------------------------------------------
  249. //    SWCloneSprite
  250. ///--------------------------------------------------------------------------------------
  251.  
  252. SW_PASCAL OSErr SWCloneSprite(
  253.     SpritePtr cloneSpriteP,
  254.     SpritePtr* newSpriteP,
  255.     void* spriteStorageP)
  256. {
  257.     OSErr err;
  258.     SpritePtr tempSpriteP;
  259.     TimeTaskRec moveTimeTask, frameTimeTask;
  260.     short frame;
  261.  
  262.     err = SWCreateSprite(&tempSpriteP, spriteStorageP, cloneSpriteP->maxFrames);
  263.  
  264.     if (err == noErr)
  265.     {
  266.             // save off the time tasks, these are unique to a particular sprite
  267.         moveTimeTask = tempSpriteP->moveTimeTask;
  268.         frameTimeTask = tempSpriteP->frameTimeTask;
  269.  
  270.             // copy the clone sprite into the temp sprite
  271.         *tempSpriteP = *cloneSpriteP;
  272.  
  273.             // restore the time tasks
  274.         tempSpriteP->moveTimeTask = moveTimeTask;
  275.         tempSpriteP->frameTimeTask = frameTimeTask;
  276.  
  277.             // clear the next and prev fields, just in case
  278.         tempSpriteP->nextSpriteP = NULL;
  279.         tempSpriteP->prevSpriteP = NULL;
  280.  
  281.             // copy the frame array
  282.         for (frame = 0; frame < tempSpriteP->maxFrames; frame++)
  283.         {
  284.             tempSpriteP->frameArray[frame] = cloneSpriteP->frameArray[frame];
  285.         }
  286.  
  287.         *newSpriteP = tempSpriteP;
  288.     }
  289.  
  290.     return err;
  291. }
  292.  
  293.  
  294. ///--------------------------------------------------------------------------------------
  295. //    SWDisposeSprite
  296. ///--------------------------------------------------------------------------------------
  297.  
  298. SW_PASCAL void SWDisposeSprite(
  299.     SpritePtr deadSpriteP,
  300.     Boolean disposeFrames)
  301. {
  302.     SWCloseSprite(deadSpriteP, disposeFrames);
  303.  
  304.     DisposePtr((Ptr)deadSpriteP);
  305. }
  306.  
  307.  
  308. ///--------------------------------------------------------------------------------------
  309. //    SWCloseSprite
  310. ///--------------------------------------------------------------------------------------
  311.  
  312. SW_PASCAL void SWCloseSprite(
  313.     SpritePtr deadSpriteP,
  314.     Boolean disposeFrames)
  315. {
  316.     short frame;
  317.  
  318.     if (deadSpriteP != NULL)
  319.     {
  320.             // remove the sprite time tasks from the time manager queue
  321.         RmvTime((QElemPtr)&deadSpriteP->moveTimeTask);
  322.         RmvTime((QElemPtr)&deadSpriteP->frameTimeTask);
  323.  
  324.         if (disposeFrames)
  325.         {
  326.             for (frame = 0; frame < deadSpriteP->numFrames; frame++)
  327.             {
  328.                 SWDisposeFrame(deadSpriteP->frameArray[frame]);
  329.             }
  330.         }
  331.  
  332.         DisposePtr((Ptr)deadSpriteP->frameArray);
  333.     }
  334. }
  335.  
  336.  
  337. ///--------------------------------------------------------------------------------------
  338. //    SWLockSprite
  339. ///--------------------------------------------------------------------------------------
  340.  
  341. SW_PASCAL void SWLockSprite(
  342.     SpritePtr srcSpriteP)
  343. {
  344.     register long numFrames;
  345.  
  346.         // is the sprite not locked?
  347.     numFrames = srcSpriteP->numFrames;
  348.  
  349.     while (numFrames--)
  350.     {
  351.         SWLockFrame(srcSpriteP->frameArray[numFrames]);
  352.     }
  353. }
  354.  
  355.  
  356. ///--------------------------------------------------------------------------------------
  357. //    SWUnlockSprite
  358. ///--------------------------------------------------------------------------------------
  359.  
  360. SW_PASCAL void SWUnlockSprite(
  361.     SpritePtr srcSpriteP)
  362. {
  363.     register long numFrames;
  364.  
  365.         // is the sprite locked?
  366.     numFrames = srcSpriteP->numFrames;
  367.  
  368.     while (numFrames--)
  369.     {
  370.         SWUnlockFrame(srcSpriteP->frameArray[numFrames]);
  371.     }
  372. }
  373.  
  374.  
  375. ///--------------------------------------------------------------------------------------
  376. //    SWSetSpriteDrawProc
  377. ///--------------------------------------------------------------------------------------
  378.  
  379. SW_PASCAL void SWSetSpriteDrawProc(
  380.     SpritePtr srcSpriteP,
  381.     DrawProcPtr drawProc)
  382. {
  383.     srcSpriteP->frameDrawProc = drawProc;
  384. }
  385.  
  386.  
  387. ///--------------------------------------------------------------------------------------
  388. //    SWStdDrawProc
  389. ///--------------------------------------------------------------------------------------
  390.  
  391. SW_PASCAL void SWStdDrawProc(
  392.     FramePtr srcFrameP,
  393.     FramePtr dstFrameP,
  394.     Rect* srcRect,
  395.     Rect* dstRect)
  396. {
  397.         // by the way, CopyBits with a mask region is 60% faster than CopyMask!
  398.     CopyBits((BitMapPtr)srcFrameP->framePix.pixMapP, (BitMapPtr)dstFrameP->framePix.pixMapP,
  399.                 srcRect, dstRect, srcCopy, srcFrameP->maskRgn);
  400. }
  401.  
  402.  
  403. ///--------------------------------------------------------------------------------------
  404. //    SWStdMaskDrawProc
  405. ///--------------------------------------------------------------------------------------
  406.  
  407. SW_PASCAL void SWStdMaskDrawProc(
  408.     FramePtr srcFrameP,
  409.     FramePtr dstFrameP,
  410.     Rect* srcRect,
  411.     Rect* dstRect,
  412.     RgnHandle maskRgn)
  413. {
  414.         // by the way, CopyBits with a mask region is 60% faster than CopyMask!
  415.     CopyBits((BitMapPtr)srcFrameP->framePix.pixMapP, (BitMapPtr)dstFrameP->framePix.pixMapP,
  416.                 srcRect, dstRect, srcCopy, maskRgn);
  417. }
  418.  
  419.  
  420. ///--------------------------------------------------------------------------------------
  421. //    SWAddFrame
  422. ///--------------------------------------------------------------------------------------
  423.  
  424. SW_PASCAL OSErr SWAddFrame(
  425.     SpritePtr srcSpriteP,
  426.     FramePtr newFrameP)
  427. {
  428.     OSErr err = noErr;
  429.  
  430.         // don’t exceed maximum number of frames
  431.     if (srcSpriteP->numFrames < srcSpriteP->maxFrames)
  432.     {
  433.         srcSpriteP->frameArray[srcSpriteP->numFrames] = newFrameP;
  434.  
  435.             // increment the number of frames
  436.         srcSpriteP->numFrames++;
  437.  
  438.         SWSetCurrentFrame(srcSpriteP, srcSpriteP->frameArray[0]);
  439.     }
  440.     else
  441.     {
  442.         err = kMaxFramesErr;
  443.     }
  444.  
  445.     return err;
  446. }
  447.  
  448.  
  449. ///--------------------------------------------------------------------------------------
  450. //    SWRemoveFrame
  451. ///--------------------------------------------------------------------------------------
  452.  
  453. SW_PASCAL void SWRemoveFrame(
  454.     SpritePtr srcSpriteP,
  455.     FramePtr oldFrameP)
  456. {
  457.     register long numFrames;
  458.     register FramePtr *frameArray;
  459.  
  460.     numFrames = srcSpriteP->numFrames;
  461.     frameArray = srcSpriteP->frameArray;
  462.  
  463.         // find the frame to be removed
  464.     while (numFrames--)
  465.     {
  466.         if (frameArray[numFrames] == oldFrameP)
  467.         {
  468.                 // move the rest of the frames down
  469.             while (numFrames < (srcSpriteP->numFrames - 1L))
  470.             {
  471.                 frameArray[numFrames] = frameArray[numFrames + 1L];
  472.  
  473.                 numFrames++;
  474.             }
  475.  
  476.             break;
  477.         }
  478.     }
  479. }
  480.  
  481.  
  482. ///--------------------------------------------------------------------------------------
  483. //    SWSetCurrentFrame
  484. ///--------------------------------------------------------------------------------------
  485.  
  486. SW_PASCAL void SWSetCurrentFrame(
  487.     SpritePtr srcSpriteP,
  488.     FramePtr newFrameP)
  489. {
  490.     Rect lastRect, rgnRect;
  491.     short horizOffset, vertOffset;
  492.  
  493.     if (srcSpriteP->curFrameP != newFrameP)
  494.     {
  495.         srcSpriteP->curFrameP = newFrameP;
  496.  
  497.         lastRect = srcSpriteP->destFrameRect;
  498.  
  499.         srcSpriteP->destFrameRect = newFrameP->frameRect;
  500.  
  501.         horizOffset = (lastRect.left - srcSpriteP->destFrameRect.left);
  502.         vertOffset = (lastRect.top - srcSpriteP->destFrameRect.top);
  503.  
  504.         srcSpriteP->destFrameRect.left += horizOffset;
  505.         srcSpriteP->destFrameRect.right += horizOffset;
  506.         srcSpriteP->destFrameRect.top += vertOffset;
  507.         srcSpriteP->destFrameRect.bottom += vertOffset;
  508.  
  509.         srcSpriteP->needsToBeDrawn = true;
  510.     }
  511. }
  512.  
  513.  
  514. ///--------------------------------------------------------------------------------------
  515. //    SWSetCurrentFrameIndex
  516. ///--------------------------------------------------------------------------------------
  517.  
  518. SW_PASCAL void SWSetCurrentFrameIndex(
  519.     SpritePtr srcSpriteP,
  520.     short frameIndex)
  521. {
  522.     register FramePtr newFrameP;
  523.     Rect lastRect, rgnRect;
  524.     short horizOffset, vertOffset;
  525.  
  526.     if (frameIndex < srcSpriteP->numFrames)
  527.     {
  528.         newFrameP = srcSpriteP->frameArray[frameIndex];
  529.  
  530.         srcSpriteP->curFrameP = newFrameP;
  531.  
  532.         lastRect = srcSpriteP->destFrameRect;
  533.  
  534.         srcSpriteP->destFrameRect = newFrameP->frameRect;
  535.  
  536.         horizOffset = (lastRect.left - srcSpriteP->destFrameRect.left);
  537.         vertOffset = (lastRect.top - srcSpriteP->destFrameRect.top);
  538.  
  539.         srcSpriteP->destFrameRect.left += horizOffset;
  540.         srcSpriteP->destFrameRect.right += horizOffset;
  541.         srcSpriteP->destFrameRect.top += vertOffset;
  542.         srcSpriteP->destFrameRect.bottom += vertOffset;
  543.  
  544.         srcSpriteP->needsToBeDrawn = true;
  545.     }
  546. }
  547.  
  548.  
  549. ///--------------------------------------------------------------------------------------
  550. //    SWSetSpriteFrameAdvance
  551. ///--------------------------------------------------------------------------------------
  552.  
  553. SW_PASCAL void SWSetSpriteFrameAdvance(
  554.     SpritePtr srcSpriteP,
  555.     short frameAdvance)
  556. {
  557.     srcSpriteP->frameAdvance = frameAdvance;
  558. }
  559.  
  560.  
  561. ///--------------------------------------------------------------------------------------
  562. //    SWSetSpriteFrameRange
  563. ///--------------------------------------------------------------------------------------
  564.  
  565. SW_PASCAL void SWSetSpriteFrameRange(
  566.     SpritePtr srcSpriteP,
  567.     short firstFrameIndex,
  568.     short lastFrameIndex)
  569. {
  570.     srcSpriteP->firstFrameIndex = firstFrameIndex;
  571.     srcSpriteP->lastFrameIndex = lastFrameIndex;
  572. }
  573.  
  574.  
  575. ///--------------------------------------------------------------------------------------
  576. //    SWSetSpriteFrameTime
  577. ///--------------------------------------------------------------------------------------
  578.  
  579. SW_PASCAL void SWSetSpriteFrameTime(
  580.     SpritePtr srcSpriteP,
  581.     long timeInterval)
  582. {
  583.     srcSpriteP->frameTimeInterval = timeInterval;
  584.  
  585.         // is the time interval positive?
  586.     if (timeInterval > 0)
  587.     {
  588.             // if the task is not already primed…
  589.         if (!SWIsTaskPrimed(&srcSpriteP->frameTimeTask.timeTask))
  590.         {
  591.                 // …prime it
  592.             srcSpriteP->frameTimeTask.hasTaskFired = true;
  593.         }
  594.     }
  595.         // is the time interval negative?
  596.     else if (timeInterval < 0)
  597.     {
  598.             // if the task is primed…
  599.         if (SWIsTaskPrimed(&srcSpriteP->frameTimeTask.timeTask))
  600.         {
  601.                 // …remove it
  602.             RmvTime((QElemPtr)&srcSpriteP->frameTimeTask);
  603.             InsTime((QElemPtr)&srcSpriteP->frameTimeTask);
  604.         }
  605.  
  606.             // the timeInterval is negative, which means never change the frame
  607.         srcSpriteP->frameTimeTask.hasTaskFired = false;
  608.     }
  609.         // is the time interval zero?
  610.     else
  611.     {
  612.             // this means change frames as quickly as possible
  613.         srcSpriteP->frameTimeTask.hasTaskFired = true;
  614.     }
  615. }
  616.  
  617.  
  618. ///--------------------------------------------------------------------------------------
  619. //    SWSetSpriteFrameProc
  620. ///--------------------------------------------------------------------------------------
  621.  
  622. SW_PASCAL void SWSetSpriteFrameProc(
  623.     SpritePtr srcSpriteP,
  624.     FrameProcPtr frameProc)
  625. {
  626.     srcSpriteP->frameChangeProc = frameProc;
  627. }
  628.  
  629.  
  630. ///--------------------------------------------------------------------------------------
  631. //    SWMoveSprite
  632. ///--------------------------------------------------------------------------------------
  633.  
  634. SW_PASCAL void SWMoveSprite(
  635.     SpritePtr srcSpriteP,
  636.     short horizLoc,
  637.     short vertLoc)
  638. {
  639.     if ((horizLoc != 0) || (vertLoc != 0))
  640.     {
  641.         srcSpriteP->destFrameRect.bottom = vertLoc + (srcSpriteP->destFrameRect.bottom -
  642.                                                     srcSpriteP->destFrameRect.top);
  643.         srcSpriteP->destFrameRect.right = horizLoc + (srcSpriteP->destFrameRect.right -
  644.                                                     srcSpriteP->destFrameRect.left);
  645.         srcSpriteP->destFrameRect.top = vertLoc;
  646.         srcSpriteP->destFrameRect.left = horizLoc;
  647.  
  648.         srcSpriteP->needsToBeDrawn = true;
  649.     }
  650. }
  651.  
  652.  
  653. ///--------------------------------------------------------------------------------------
  654. //    SWOffsetSprite
  655. ///--------------------------------------------------------------------------------------
  656.  
  657. SW_PASCAL void SWOffsetSprite(
  658.     SpritePtr srcSpriteP,
  659.     short horizDelta,
  660.     short vertDelta)
  661. {
  662.     if ((horizDelta != 0) || (vertDelta != 0))
  663.     {
  664.         srcSpriteP->destFrameRect.right += horizDelta;
  665.         srcSpriteP->destFrameRect.bottom += vertDelta;
  666.         srcSpriteP->destFrameRect.left += horizDelta;
  667.         srcSpriteP->destFrameRect.top += vertDelta;
  668.  
  669.         srcSpriteP->needsToBeDrawn = true;
  670.     }
  671. }
  672.  
  673.  
  674. ///--------------------------------------------------------------------------------------
  675. //    SWSetSpriteLocation
  676. ///--------------------------------------------------------------------------------------
  677.  
  678. SW_PASCAL void SWSetSpriteLocation(
  679.     SpritePtr srcSpriteP,
  680.     short horizLoc,
  681.     short vertLoc)
  682. {
  683.     srcSpriteP->destFrameRect.bottom = vertLoc + (srcSpriteP->destFrameRect.bottom -
  684.                                                 srcSpriteP->destFrameRect.top);
  685.     srcSpriteP->destFrameRect.right = horizLoc + (srcSpriteP->destFrameRect.right -
  686.                                                 srcSpriteP->destFrameRect.left);
  687.     srcSpriteP->destFrameRect.top = vertLoc;
  688.     srcSpriteP->destFrameRect.left = horizLoc;
  689.  
  690.     srcSpriteP->deltaFrameRect = srcSpriteP->destFrameRect;
  691.     srcSpriteP->oldFrameRect = srcSpriteP->destFrameRect;
  692. }
  693.  
  694.  
  695. ///--------------------------------------------------------------------------------------
  696. //    SWSetSpriteMoveBounds
  697. ///--------------------------------------------------------------------------------------
  698.  
  699. SW_PASCAL void SWSetSpriteMoveBounds(
  700.     SpritePtr srcSpriteP,
  701.     Rect* moveBoundsRect)
  702. {
  703.     srcSpriteP->moveBoundsRect = *moveBoundsRect;
  704. }
  705.  
  706.  
  707. ///--------------------------------------------------------------------------------------
  708. //    SWSetSpriteMoveDelta
  709. ///--------------------------------------------------------------------------------------
  710.  
  711. SW_PASCAL void SWSetSpriteMoveDelta(
  712.     SpritePtr srcSpriteP,
  713.     short horizDelta,
  714.     short vertDelta)
  715. {
  716.         // set sprite’s velocity
  717.     srcSpriteP->horizMoveDelta = horizDelta;
  718.     srcSpriteP->vertMoveDelta = vertDelta;
  719. }
  720.  
  721.  
  722. ///--------------------------------------------------------------------------------------
  723. //    SWSetSpriteMoveTime
  724. ///--------------------------------------------------------------------------------------
  725.  
  726. SW_PASCAL void SWSetSpriteMoveTime(
  727.     SpritePtr srcSpriteP,
  728.     long timeInterval)
  729. {
  730.     srcSpriteP->moveTimeInterval = timeInterval;
  731.  
  732.         // is the time interval positive?
  733.     if (timeInterval > 0)
  734.     {
  735.             // if the task is not already primed…
  736.         if (!SWIsTaskPrimed(&srcSpriteP->moveTimeTask.timeTask))
  737.         {
  738.                 // …prime it
  739.             srcSpriteP->moveTimeTask.hasTaskFired = true;
  740.         }
  741.     }
  742.         // is the time interval negative?
  743.     else if (timeInterval < 0)
  744.     {
  745.             // if the task is primed…
  746.         if (SWIsTaskPrimed(&srcSpriteP->moveTimeTask.timeTask))
  747.         {
  748.                 // …remove it
  749.             RmvTime((QElemPtr)&srcSpriteP->moveTimeTask);
  750.             InsTime((QElemPtr)&srcSpriteP->moveTimeTask);
  751.         }
  752.  
  753.             // the timeInterval is negative, which means never change the frame
  754.         srcSpriteP->moveTimeTask.hasTaskFired = false;
  755.     }
  756.         // is the time interval zero?
  757.     else
  758.     {
  759.             // this means change frames as quickly as possible
  760.         srcSpriteP->moveTimeTask.hasTaskFired = true;
  761.     }
  762. }
  763.  
  764.  
  765. ///--------------------------------------------------------------------------------------
  766. //    SWSetSpriteMoveProc
  767. ///--------------------------------------------------------------------------------------
  768.  
  769. SW_PASCAL void SWSetSpriteMoveProc(
  770.     SpritePtr srcSpriteP,
  771.     MoveProcPtr moveProc)
  772. {
  773.     srcSpriteP->spriteMoveProc = moveProc;
  774. }
  775.  
  776.  
  777. ///--------------------------------------------------------------------------------------
  778. //    SWBounceSpriteMoveProc
  779. ///--------------------------------------------------------------------------------------
  780.  
  781. SW_PASCAL void SWBounceSpriteMoveProc(
  782.     SpritePtr srcSpriteP,
  783.     Point* spritePoint)
  784. {
  785.     if (srcSpriteP->destFrameRect.left < srcSpriteP->moveBoundsRect.left)
  786.     {
  787.         srcSpriteP->horizMoveDelta = -srcSpriteP->horizMoveDelta;
  788.         spritePoint->h = srcSpriteP->moveBoundsRect.left;
  789.     }
  790.     else if (srcSpriteP->destFrameRect.right > srcSpriteP->moveBoundsRect.right)
  791.     {
  792.         srcSpriteP->horizMoveDelta = -srcSpriteP->horizMoveDelta;
  793.         spritePoint->h = srcSpriteP->moveBoundsRect.right -
  794.             (srcSpriteP->curFrameP->frameRect.right - srcSpriteP->curFrameP->frameRect.left);
  795.     }
  796.  
  797.     if (srcSpriteP->destFrameRect.top < srcSpriteP->moveBoundsRect.top)
  798.     {
  799.         srcSpriteP->vertMoveDelta = -srcSpriteP->vertMoveDelta;
  800.         spritePoint->v = srcSpriteP->moveBoundsRect.top;
  801.     }
  802.     else if (srcSpriteP->destFrameRect.bottom > srcSpriteP->moveBoundsRect.bottom)
  803.     {
  804.         srcSpriteP->vertMoveDelta = -srcSpriteP->vertMoveDelta;
  805.         spritePoint->v = srcSpriteP->moveBoundsRect.bottom -
  806.             (srcSpriteP->curFrameP->frameRect.bottom - srcSpriteP->curFrameP->frameRect.top);
  807.     }
  808. }
  809.  
  810.  
  811. ///--------------------------------------------------------------------------------------
  812. //    SWWrapSpriteMoveProc
  813. ///--------------------------------------------------------------------------------------
  814.  
  815. SW_PASCAL void SWWrapSpriteMoveProc(
  816.     SpritePtr srcSpriteP,
  817.     Point* spritePoint)
  818. {
  819.     Point oldSpritePoint = *spritePoint;
  820.  
  821.     if (srcSpriteP->destFrameRect.left > srcSpriteP->moveBoundsRect.right)
  822.     {
  823.         spritePoint->h = srcSpriteP->moveBoundsRect.left -
  824.                                 (srcSpriteP->destFrameRect.right - 
  825.                                 srcSpriteP->destFrameRect.left);
  826.     }
  827.     else if (srcSpriteP->destFrameRect.right < srcSpriteP->moveBoundsRect.left)
  828.     {
  829.         spritePoint->h = srcSpriteP->moveBoundsRect.right;
  830.     }
  831.  
  832.     if (srcSpriteP->destFrameRect.top > srcSpriteP->moveBoundsRect.bottom)
  833.     {
  834.         spritePoint->v = srcSpriteP->moveBoundsRect.top -
  835.                                 (srcSpriteP->destFrameRect.bottom - 
  836.                                 srcSpriteP->destFrameRect.top);
  837.     }
  838.     else if (srcSpriteP->destFrameRect.bottom < srcSpriteP->moveBoundsRect.top)
  839.     {
  840.         spritePoint->v = srcSpriteP->moveBoundsRect.bottom;
  841.     }
  842.  
  843.     if ((spritePoint->h != oldSpritePoint.h) || (spritePoint->v != oldSpritePoint.v))
  844.     {
  845.         SWSetSpriteLocation(srcSpriteP, spritePoint->h, spritePoint->v);
  846.     }    
  847. }
  848.  
  849.  
  850. ///--------------------------------------------------------------------------------------
  851. //    SWSetSpriteCollideProc
  852. ///--------------------------------------------------------------------------------------
  853.  
  854. SW_PASCAL void SWSetSpriteCollideProc(
  855.     SpritePtr srcSpriteP,
  856.     CollideProcPtr collideProc)
  857. {
  858.     srcSpriteP->spriteCollideProc = collideProc;
  859. }
  860.  
  861.  
  862. ///--------------------------------------------------------------------------------------
  863. //    SWSetSpriteVisible
  864. ///--------------------------------------------------------------------------------------
  865.  
  866. SW_PASCAL void SWSetSpriteVisible(
  867.     SpritePtr srcSpriteP,
  868.     Boolean isVisible)
  869. {
  870.     srcSpriteP->isVisible = isVisible;
  871.     srcSpriteP->needsToBeDrawn = true;
  872.     srcSpriteP->needsToBeErased = !isVisible;
  873. }
  874.  
  875.  
  876. ///--------------------------------------------------------------------------------------
  877. //    SWIsSpriteInRect
  878. ///--------------------------------------------------------------------------------------
  879.  
  880. SW_PASCAL Boolean SWIsSpriteInRect(
  881.     SpritePtr srcSpriteP,
  882.     Rect* testRect)
  883. {
  884.     return (!((srcSpriteP->destFrameRect.top >= testRect->bottom) ||
  885.                 (srcSpriteP->destFrameRect.bottom <= testRect->top) ||
  886.                  (srcSpriteP->destFrameRect.left >= testRect->right) ||
  887.                  (srcSpriteP->destFrameRect.right <= testRect->left)));
  888. }
  889.  
  890.  
  891. ///--------------------------------------------------------------------------------------
  892. //    SWTimeTask
  893. ///--------------------------------------------------------------------------------------
  894.  
  895. #ifndef THINK_C
  896.  
  897. TimeTaskPtr SWGetTimeTask(void) = 0x2009;    // move.l  A1, D0
  898.  
  899. #endif
  900.  
  901. pascal void SWTimeTask(void)
  902. {
  903.         // on entry a pointer to our time task is in A1
  904.  
  905. #ifdef THINK_C
  906.  
  907.         // THINK C’s inline assembly is very convenient
  908.     asm
  909.     {
  910.         move.b    #true, TimeTaskRec.hasTaskFired(A1)
  911.     }
  912.  
  913. #else
  914.  
  915.         // but, this might be compiled with
  916.         // MPW C, Symantec C++ for MPW, or THINK C++
  917.         // which don’t support inline assembly!!!
  918.     SWGetTimeTask()->hasTaskFired = true;
  919.  
  920. #endif
  921. }
  922.  
  923.  
  924. ///--------------------------------------------------------------------------------------
  925. //    SWIsTaskPrimed
  926. ///--------------------------------------------------------------------------------------
  927.  
  928. SW_PASCAL Boolean SWIsTaskPrimed(
  929.     TMTask* tmTaskP)
  930. {
  931.     return (tmTaskP->qType & 0x8000) != 0;
  932. }
  933.  
  934.